﻿// <copyright file="Program.cs" company="Hallvard Korsgaard">
//  Microsoft Public License (Ms-PL). See license details here: http://enoceannet.codeplex.com/license
// </copyright>
// <author>Hallvard Korsgaard</author>

namespace Receive
{
  using System;
  using System.Collections.Generic;
  using System.Net;
  using System.Text;
  using StcEthernet;

  /// <summary>
  /// Shows how to receive telegrams from STC-Ethernet transievers.
  /// </summary>
  public class Program
  {
    /// <summary>
    /// This variable is used for synchronizing write access to the console.
    /// </summary>
    private static readonly object lck = new object();

    /// <summary>
    /// Used for keeping track of the transievers so we can clean up before exiting.
    /// </summary>
    private static readonly List<Transiever> transievers = new List<Transiever>();

    /// <summary>
    /// Application starts here.
    /// </summary>
    public static void Main()
    {
      IPAddress serverAddress;
      IPEndPoint serverEndpoint;
      Server server;

      // Create a new server listening on TCP port 4000.
      serverAddress = IPAddress.Parse("192.168.188.108");
      serverEndpoint = new IPEndPoint(serverAddress, 4000);
      server = new Server(serverEndpoint);

      // Hook up the event handlers.
      server.TransieverConnected += new EventHandler<TransieverConnectedEventArgs>(TransieverConnected);
      server.TransieverInitialized += new EventHandler<TransieverInitializedEventArgs>(TransieverInitialized);
      
      // Start to accept connections.
      server.Accept();

      lock (lck)
      {
        Console.WriteLine();
        Console.WriteLine("Press any key to exit.");
        Console.WriteLine();
      }

      Console.ReadKey();
      
      // Stop the server
      server.Close();

      // Close Transiever objects
      lock (transievers)
      {
        foreach (Transiever t in transievers)
        {
          t.Close();
        }
      }
    }
    
    /// <summary>
    /// This event handler will be called when a transiever connects.
    /// The event handler code must be thread safe because several events can fire at the same time.
    /// </summary>
    /// <param name="sender">The object that sent the event.</param>
    /// <param name="e">The event data.</param>
    private static void TransieverConnected(object sender, TransieverConnectedEventArgs e)
    {
      lock (lck)
      {
        Console.WriteLine("Transiever connected.");
      }

      lock (transievers)
      {
        transievers.Add(e.Transiever);
      }
    }

    /// <summary>
    /// This event handler will be called when the Transiever object is ready for use.
    /// The event handler code must be thread safe because several events can fire at the same time.
    /// </summary>
    /// <param name="sender">The object that sent the event.</param>
    /// <param name="e">The event data.</param>
     private static void TransieverInitialized(object sender, TransieverInitializedEventArgs e)
    {
      lock (lck)
      {
        Console.WriteLine("Transiever initialized.");
        Console.WriteLine("Base ID          : " + e.Transiever.BaseId.ToString("X8"));
        Console.WriteLine("Modem on         : " + e.Transiever.IsModemOn);
        Console.WriteLine("Modem ID         : " + e.Transiever.ModemId.ToString("X4"));
        Console.WriteLine("Operating mode   : " + e.Transiever.OperatingMode);
        Console.WriteLine("Radio sensitivity: " + e.Transiever.RadioSensitivity);
        Console.WriteLine("Software version : " + e.Transiever.SoftwareVersion);
      }

      // Hooking up event handlers.
      e.Transiever.TelegramReceived += new EventHandler<TelegramReceivedEventArgs>(Transiever_TelegramReceived);
      e.Transiever.ManagementTelegramReceived += new EventHandler<ManagementTelegramReceivedEventArgs>(Transiever_ManagementTelegramReceived);
      e.Transiever.UnknownTelegramReceived += new EventHandler<UnknownDataReceivedEventArgs>(Transiever_UnknownTelegramReceived);
      e.Transiever.ResponseTimeout += new EventHandler<ResponseTimeoutEventArgs>(Transiever_ResponseTimeout);
      e.Transiever.TransieverDisconnected += new EventHandler<TransieverDisconnectedEventArgs>(Transiever_TransieverDisconnected);
    }

    /// <summary>
    /// The event fires when a telegram is received from the transiever.
    /// The event handler code must be thread safe because several events can fire at the same time.
    /// </summary>
    /// <param name="sender">The object that sent the event.</param>
    /// <param name="e">The event data.</param>
    private static void Transiever_TelegramReceived(object sender, TelegramReceivedEventArgs e)
    {
      lock (lck)
      {
        Console.WriteLine();
        Console.WriteLine(DateTime.Now);
        Console.WriteLine("Telegram: " + e.Telegram.GetType().ToString() + " " + e.Telegram);
      }
    }

    /// <summary>
    /// The event fires when a management telegram is received from the transiever.
    /// The event handler code must be thread safe because several events can fire at the same time.
    /// </summary>
    /// <param name="sender">The object that sent the event.</param>
    /// <param name="e">The event data.</param>
    private static void Transiever_ManagementTelegramReceived(object sender, ManagementTelegramReceivedEventArgs e)
    {
      lock (lck)
      {
        Console.WriteLine();
        Console.WriteLine(DateTime.Now);
        Console.WriteLine("Management telegram: " + e.Telegram.GetType().ToString() + " " + e.Telegram);
      }
    }

    /// <summary>
    /// This event handler will be called when if unrecognizable information is received.
    /// The event handler code must be thread safe because several events can fire at the same time.
    /// </summary>
    /// <param name="sender">The object that sent the event.</param>
    /// <param name="e">The event data.</param>
    private static void Transiever_UnknownTelegramReceived(object sender, UnknownDataReceivedEventArgs e)
    {
      lock (lck)
      {
        Console.WriteLine();
        Console.WriteLine(DateTime.Now);
        Console.WriteLine("Unknown telegram: " + Encoding.ASCII.GetString(e.Data));
        Console.WriteLine(e.Exception);
      }
    }

    /// <summary>
    /// This event handler will be called if an expected response message is not received when sending a message.
    /// The event handler code must be thread safe because several events can fire at the same time.
    /// </summary>
    /// <param name="sender">The object that sent the event.</param>
    /// <param name="e">The event data.</param>
    private static void Transiever_ResponseTimeout(object sender, ResponseTimeoutEventArgs e)
    {
      lock (lck)
      {
        Console.WriteLine();
        Console.WriteLine(DateTime.Now);
        Console.WriteLine("Response timeout.");
      }
    }

    /// <summary>
    /// This event handler will be called when a transiever disconnects.
    /// The event handler code must be thread safe because several events can fire at the same time.
    /// </summary>
    /// <param name="sender">The object that sent the event.</param>
    /// <param name="e">The event data.</param>
    private static void Transiever_TransieverDisconnected(object sender, TransieverDisconnectedEventArgs e)
    {
      lock (lck)
      {
        Console.WriteLine();
        Console.WriteLine(DateTime.Now);
        Console.WriteLine("Transiever disconnected.");
      }

      lock (transievers)
      {
        transievers.Remove(e.Transiever);
      }

      // The Transiever object will call the Close method on itself after this event handler returns.
    }
  }
}
